﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace SPC.Chart
{
    public partial class BarChart : UserControl
    {
        double[] bounds;
        int[] groupCounts;
        double u,sigma;
        EGroupingPolicy gPolicy = EGroupingPolicy.normal;
        int decimals = 0;
        public EGroupingPolicy GroupingPolicy
            {
            set { gPolicy = value; }
            get { return gPolicy; }
            }        
        public BarChart()
        {
            InitializeComponent();
            chart1.Series[0].ChartType = SeriesChartType.Bar;
            chart1.Legends.Clear();
            
        }
        public bool RefreshChart()
        {
            if(groupCounts.Length>0)
            {
                chart1.Series[0].Points.Clear();
                chart1.Series.Clear();
                
                chart1.Series.Add("BAR");
                for (int i = 0; i < groupCounts.Length; i++)
                {
                    double x = Math.Round(bounds[i], decimals);// double.Parse(bounds[i].ToString("G3"));
                    chart1.Series[0].Points.AddXY(x, groupCounts[i]);
                    
                }
                DrawGauss(u, sigma, groupCounts.Max());
                return true;
            }
            else
            { return false; }
            
        }
        /// <summary>
        /// 绘制正态分布曲线f(x)=exp(-(x-u)^2/2sigma^2)/sqrt(2PI*sigma)
        /// </summary>
        /// <param name="u"></param>
        /// <param name="sigma"></param>
        /// <param name="maxValue">maxValue=0时，最大值为标准值1/sqrt(1/2*pi*sigma)</param>
        private void DrawGauss( double u, double sigma,double maxValue=0)
        {
            double[] x = new double[51];
            double[] y = new double[51];
            double xStart = u - 3 * sigma;
            double xStop = u + 3 * sigma;
            if(maxValue==0)
            {
                maxValue = 1 / (Math.Sqrt(2 * Math.PI * sigma));
            }
            
            for (int i = 0; i < x.Length; i++)
            {
                x[i] = xStart + i * 6 * sigma / (x.Length - 1);
                double pow = -sq((x[i] - u) / sigma) / 2;
                y[i] =maxValue* Math.Pow(Math.E, pow);
            }
            chart1.Series.Add("Gauss");
            chart1.Series["Gauss"].ChartType = SeriesChartType.Spline;
            chart1.Series["Gauss"].Color = Color.Blue;
            for (int i = 0; i < x.Length; i++)
            {
                double xi = Math.Round(x[i], decimals*2);
                chart1.Series["Gauss"].Points.AddXY(xi, y[i]);
            }
        }
        private double sq(double x)
        {
            return x * x;
        }
        public void SendData(double[][] data)
        {
            for (int i = 0; i < data[0].Length; i++)
            {
                string s = data[0][i].ToString();
                s = s.Substring(s.IndexOf('.') + 1);
                int num = s.Length;
                if (num > decimals) decimals = num;
            }
            List<double> dList = new List<double>();
            for (int i = 0; i < data.Length; i++)
            {
                for (int j = 0; j < data[i].Length; j++)
                {
                    dList.Add(data[i][j]);
                }
            }
            SendData(dList.ToArray());
        }
        public void SendData(double[] data)
        {
            //1确定分组数
            switch(gPolicy)
            {
                case EGroupingPolicy.small:
                    if (data.Length < 50)
                        groupCounts = new int[5];
                    else if(data.Length<100)
                        groupCounts = new int[6];
                    else if(data.Length<250)
                        groupCounts = new int[7];
                    else 
                        groupCounts = new int[10];
                    break;
                case EGroupingPolicy.large:
                    if (data.Length < 50)
                        groupCounts = new int[7];
                    else if (data.Length < 100)
                        groupCounts = new int[10];
                    else if (data.Length < 250)
                        groupCounts = new int[12];
                    else
                        groupCounts = new int[20];
                    break;
                default:
                    if (data.Length < 50)
                        groupCounts = new int[6];
                    else if (data.Length < 100)
                        groupCounts = new int[8];
                    else if (data.Length < 250)
                        groupCounts = new int[10];
                    else
                        groupCounts = new int[15];
                    break;
            }
            //2.分组计数
            double range = data.Max() - data.Min();//计算极差
            double h = range / groupCounts.Length; //计算组距
            bounds = new double[groupCounts.Length];
            for (int i = 0; i < bounds.Length; i++)
            {
                bounds[i] = data.Min() + (i+1) * h;
            }
            for (int i = 0; i < data.Length; i++)
            {
                for (int k = 0; k < bounds.Length; k++)
                {
                    if(data[i]<=bounds[k])
                    {
                        groupCounts[k]++;//分组计数
                        break;
                    }                    
                }
            }
            int count = groupCounts.Sum();
            //计算u,sigma
            u = data.Average();
            double sum = 0;
            for (int i = 0; i < data.Length; i++)
            {
                sum += Math.Pow((data[i] - u), 2);
            }
            sigma = Math.Sqrt(sum / (data.Length - 1));
        }
    }
    public enum EGroupingPolicy { small,normal,large};
    /*  数据量   组数
     *  ~50     5~7
     *  51~100  6~10
     *  101~250 7~12
     *  250~    10~20
     */
}
